﻿using System.Text;

namespace WCKYWCKF.RxUI.Model2ViewModel.Model;

public record ViewModelBuildInfo
{
    private const string INotifyPropertyChangedCode =
        """
            public event PropertyChangedEventHandler? PropertyChanged;

            protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }

            protected bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
            {
                if (!global::System.Collections.Generic.EqualityComparer<T>.Default.Equals(field, value)) return false;
                field = value;
                OnPropertyChanged(propertyName);
                return true;
            }
        """;

    public required string ViewModelName { get; init; }
    public required string GlobalSourceFQType { get; init; }
    public required string Namespace { get; init; }
    public required List<PropertyBuildInfo> Properties { get; init; }

    public string CreateViewModelCode(GenerateMode generateMode, bool useAutoField)
    {
        StringBuilder stringBuilder = new();
        stringBuilder.AppendLine(
            $$"""
              // <auto-generated/>
              #nullable enable

              using System.Linq;
              {{GetNamespaceUsing(generateMode)}}

              namespace {{Namespace}};

              public partial class {{ViewModelName}} : {{GetBaseType(generateMode)}} {

              """);
        foreach (var propertyBuildInfo in Properties)
            stringBuilder.AppendLine(propertyBuildInfo.CreatePropertyCode(generateMode, useAutoField));

        stringBuilder.AppendLine(
            $$"""

              {{(generateMode is GenerateMode.Default ? INotifyPropertyChangedCode : "")}}
              }
              #nullable disable
              """);
        return stringBuilder.ToString();
    }

    public static string GetNamespaceUsing(GenerateMode generateMode)
    {
        return generateMode switch
        {
            GenerateMode.RxUI => "using ReactiveUI;",
            GenerateMode.CommunityMvvm => "using CommunityToolkit.Mvvm.ComponentModel;",
            _ => """
                 using System.ComponentModel;
                 using System.Runtime.CompilerServices;
                 """
        };
    }

    public static string GetBaseType(GenerateMode generateMode)
    {
        return generateMode switch
        {
            GenerateMode.RxUI => "global::ReactiveUI.ReactiveObject",
            GenerateMode.CommunityMvvm => "global::CommunityToolkit.Mvvm.ComponentModel.ObservableObject",
            _ => "global::System.ComponentModel.INotifyPropertyChanged"
        };
    }
}